
#include "PCH.h"
#include "Camera.h"
#include "omp.h"
#include "constants.h"

void CCamera::SetFOV(double _FOV)
{
	FOV = _FOV;
	if(ViewportHeight>ViewportWidth)
	{
		HFOV = acos(0.0f)/90.0f*FOV;
		VFOV = double(ViewportHeight) / ViewportWidth* HFOV;
	}
	else
	{
		VFOV = acos(0.0f)/90.0f*FOV;
		HFOV = double(ViewportWidth) / ViewportHeight * VFOV;
	}

};


void CCamera::RenderScene(CScene &scene,std::vector<PixelToaster::Pixel> &pixels)
{
	CVector direction = LookAt - Position;
	direction.Normalize();
	//omp_set_num_threads(4);
	CVector right = direction.CrossProduct(CVector(0.0f, 1.0f, 0.0f));
	CVector up = right.CrossProduct(direction);
	double Exposure =2.95f;
	int yIncrement;
	switch(SubSampling)
	{
	case 2:	
		yIncrement = 4;
		break;
	case 1:
		yIncrement = 2;
		break;
	default:
		yIncrement = 1;
		break;
	}


	//#pragma omp parallel shared(pixels)
	{

		//#pragma omp for
		for(int y = 0; y < ViewportHeight-1; y+=yIncrement)
		{
			for(int x = 0; x < ViewportWidth-1; ++x)
			{
				CRay view;
				view.intensity = 1.0f;
				view.Origin = Position;
				view.BounceThreshold = MaxBounce;
				CColor ResultColor;
				// 			int x=p%ViewportWidth;
				// 			int y=(p-x)/ViewportWidth;
				double angle_x = (x * HFOV / ViewportWidth) - (HFOV / 2);
				double angle_y = (y * VFOV / ViewportHeight) - (VFOV / 2);
				if((angle_y>0)&&(angle_x>0))
					int w=0;
				view.Direction=direction*cos(angle_x)*cos(angle_y) + right*sin(angle_x)*cos(angle_y) + up*sin(angle_y);
				view.Direction.Normalize();
				scene.RenderRay(view,ResultColor);
				double r = (double)(1-exp(-1.0f*ResultColor.r*Exposure));
				double g = (double)(1-exp(-1.0f*ResultColor.g*Exposure));
				double b = (double)(1-exp(-1.0f*ResultColor.b*Exposure));

				switch(SubSampling)
				{
				case 2:
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					pixels[x+(ViewportHeight-y-2)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-2)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-2)*ViewportWidth].b=float(b);
					pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].r=float(r);
					pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].g=float(g);
					pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].b=float(b);
					pixels[x+2+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+2+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+2+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					pixels[x+3+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+3+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+3+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					pixels[x+2+(ViewportHeight-y-2)*ViewportWidth].r=float(r);
					pixels[x+2+(ViewportHeight-y-2)*ViewportWidth].g=float(g);
					pixels[x+2+(ViewportHeight-y-2)*ViewportWidth].b=float(b);
					pixels[x+3+(ViewportHeight-y-2)*ViewportWidth].r=float(r);
					pixels[x+3+(ViewportHeight-y-2)*ViewportWidth].g=float(g);
					pixels[x+3+(ViewportHeight-y-2)*ViewportWidth].b=float(b);
					pixels[x+(ViewportHeight-y-3)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-3)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-3)*ViewportWidth].b=float(b);
					pixels[x+1+(ViewportHeight-y-3)*ViewportWidth].r=float(r);
					pixels[x+1+(ViewportHeight-y-3)*ViewportWidth].g=float(g);
					pixels[x+1+(ViewportHeight-y-3)*ViewportWidth].b=float(b);
					pixels[x+(ViewportHeight-y-4)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-4)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-4)*ViewportWidth].b=float(b);
					pixels[x+1+(ViewportHeight-y-4)*ViewportWidth].r=float(r);
					pixels[x+1+(ViewportHeight-y-4)*ViewportWidth].g=float(g);
					pixels[x+1+(ViewportHeight-y-4)*ViewportWidth].b=float(b);
					pixels[x+2+(ViewportHeight-y-3)*ViewportWidth].r=float(r);
					pixels[x+2+(ViewportHeight-y-3)*ViewportWidth].g=float(g);
					pixels[x+2+(ViewportHeight-y-3)*ViewportWidth].b=float(b);
					pixels[x+3+(ViewportHeight-y-3)*ViewportWidth].r=float(r);
					pixels[x+3+(ViewportHeight-y-3)*ViewportWidth].g=float(g);
					pixels[x+3+(ViewportHeight-y-3)*ViewportWidth].b=float(b);
					pixels[x+2+(ViewportHeight-y-4)*ViewportWidth].r=float(r);
					pixels[x+2+(ViewportHeight-y-4)*ViewportWidth].g=float(g);
					pixels[x+2+(ViewportHeight-y-4)*ViewportWidth].b=float(b);
					pixels[x+3+(ViewportHeight-y-4)*ViewportWidth].r=float(r);
					pixels[x+3+(ViewportHeight-y-4)*ViewportWidth].g=float(g);
					pixels[x+3+(ViewportHeight-y-4)*ViewportWidth].b=float(b);
					++x;
					++x;
					++x;
					break;
				case 1:
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					pixels[x+(ViewportHeight-y-2)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-2)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-2)*ViewportWidth].b=float(b);
					pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].r=float(r);
					pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].g=float(g);
					pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].b=float(b);
					++x;
					break;
				default:
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].r=float(r);
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].g=float(g);
					pixels[x+(ViewportHeight-y-1)*ViewportWidth].b=float(b);
					break;
				}
			}
		}
	}
}



/*void CCamera::RenderScene2(CScene &scene,std::vector<PixelToaster::Pixel> &pixels)
{
CVector direction = LookAt - Position;
direction.Normalize();
omp_set_num_threads(1);
CVector right = direction.CrossProduct(CVector(0.0f, 1.0f, 0.0f));
CVector up = right.CrossProduct(direction);
double Exposure =2.95f;
int yIncrement;

#pragma omp parallel shared(pixels)
{

#pragma omp for
for(int y = 0; y < ViewportHeight-1; y+=yIncrement)
{
for(int x = 0; x < ViewportWidth-1; ++x)
{
CRay view;
view.intensity = 1.0f;
view.Origin = Position;
view.BounceThreshold = MaxBounce;
CColor ResultColor;
// 			int x=p%ViewportWidth;
// 			int y=(p-x)/ViewportWidth;
double angle_x = (x * HFOV / ViewportWidth) - (HFOV / 2);
double angle_y = (y * VFOV / ViewportHeight) - (VFOV / 2);
view.Direction=direction*cos(angle_x)*cos(angle_y) + right*sin(angle_x)*cos(angle_y) + up*sin(angle_y);
view.Direction.Normalize();
scene.RenderRay(view,ResultColor);
switch(SubSampling)
{
case 2:
pixels[x+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+(ViewportHeight-y-2)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-2)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-2)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+2+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+2+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+2+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+3+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+3+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+3+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+2+(ViewportHeight-y-2)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+2+(ViewportHeight-y-2)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+2+(ViewportHeight-y-2)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+3+(ViewportHeight-y-2)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+3+(ViewportHeight-y-2)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+3+(ViewportHeight-y-2)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+(ViewportHeight-y-3)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-3)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-3)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+1+(ViewportHeight-y-3)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+1+(ViewportHeight-y-3)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+1+(ViewportHeight-y-3)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+(ViewportHeight-y-4)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-4)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-4)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+1+(ViewportHeight-y-4)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+1+(ViewportHeight-y-4)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+1+(ViewportHeight-y-4)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+2+(ViewportHeight-y-3)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+2+(ViewportHeight-y-3)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+2+(ViewportHeight-y-3)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+3+(ViewportHeight-y-3)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+3+(ViewportHeight-y-3)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+3+(ViewportHeight-y-3)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+2+(ViewportHeight-y-4)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+2+(ViewportHeight-y-4)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+2+(ViewportHeight-y-4)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+3+(ViewportHeight-y-4)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+3+(ViewportHeight-y-4)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+3+(ViewportHeight-y-4)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
++x;
++x;
++x;
break;
case 1:
pixels[x+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+1+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+(ViewportHeight-y-2)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-2)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-2)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+1+(ViewportHeight-y-2)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
++x;
break;
default:
pixels[x+(ViewportHeight-y-1)*ViewportWidth].r=(double)(1-exp(-1.0f*ResultColor.r*Exposure));
pixels[x+(ViewportHeight-y-1)*ViewportWidth].g=(double)(1-exp(-1.0f*ResultColor.g*Exposure));
pixels[x+(ViewportHeight-y-1)*ViewportWidth].b=(double)(1-exp(-1.0f*ResultColor.b*Exposure));
break;
}
}
}
}
}
*/

void CCamera::Split_HDR(CColor *&pixels,CColor *&HDRpixels)
{
#pragma omp parallel shared(HDRpixels)
	{
#pragma omp for

	for(int p = 0; p < (ViewportWidth * ViewportHeight); ++p)
	{
		HDRpixels[p].r=std::max(pixels[p].r,1.0)-1.0;
		HDRpixels[p].g=std::max(pixels[p].g,1.0)-1.0;
		HDRpixels[p].b=std::max(pixels[p].b,1.0)-1.0;
	}
	}
}

double CCamera::BlurPotentialFunction(int x, int y)
{
	// 	int matrix[5][5];
	// 	matrix[0][0]=1/9.0;	matrix[1][0]=1/6.0;	matrix[2][0]=0.2; matrix[3][0]=1/6.0;	matrix[4][0]=1/9.0;
	// 	matrix[0][1]=1/6.0;	matrix[1][1]=1/3.0;	matrix[2][1]=0.5; matrix[3][1]=1/3.0;	matrix[4][1]=1/6.0;
	// 	matrix[0][2]=0.2;	matrix[1][2]=0.5;	matrix[2][2]=1;	  matrix[3][2]=0.5;		matrix[4][2]=1/0.2;
	// 	matrix[0][3]=1/6.0;	matrix[1][3]=1/3.0;	matrix[2][3]=0.5; matrix[3][3]=1/3.0;	matrix[4][3]=1/6.0;
	// 	matrix[0][4]=1/9.0;	matrix[1][4]=1/6.0;	matrix[2][4]=0.2; matrix[3][4]=1/6.0;	matrix[4][4]=1/9.0;
	// 	return matrix[x+2][y+2];

	return 1.0/(5.0+x*x+y*y);
}

void CCamera::SpecialswitchX(const int &x,int &i,int &maxi)
{
	const int maximum=100;

	if(x<maximum)
	{
		i=-x;
		maxi=maximum;
	}
	else if (x>=(ViewportWidth-maximum))
	{
		i=-maximum;
		maxi=ViewportWidth-x-1;
	}
	else
	{
		i=-maximum;
		maxi=maximum;
	}
}

void CCamera::SpecialswitchY(const int &y,int &i,int &maxi)
{
	const int maximum=100;

	if(y<maximum)
	{
		i=-y;
		maxi=maximum;
	}
	else if (y>=(ViewportHeight-maximum))
	{
		i=-maximum;
		maxi=ViewportHeight-y-1;
	}
	else
	{
		i=-maximum;
		maxi=maximum;
	}
}

void CCamera::Fuzzify_HDR(CColor *&HDRpixels)
{
	CColor *pixels=HDRpixels;

	HDRpixels = new CColor[ViewportWidth * ViewportHeight];
	omp_set_num_threads(4);
#pragma omp parallel shared(HDRpixels)
	{
#pragma omp for
	for(int y = 0; y <ViewportHeight;++y)
	{
		for(int x = 0; x <ViewportWidth;++x)
		{
			CColor temp = CColor(0,0,0);
			int i;
			int j;
			int maxi;
			int maxj;
			SpecialswitchX(x,i,maxi);
			SpecialswitchY(y,j,maxj);
			double TotalBlurPotential = 0.0;
			for(int jj = j; jj<=maxj; ++jj)
				for(int ii = i; ii<=maxi; ++ii)
				{
					double BlurPot = BlurPotentialFunction(ii,jj);
					temp +=pixels[ViewportWidth*(y+jj)+x+ii]*BlurPot;
					TotalBlurPotential +=BlurPot;
				}
			temp *=1/TotalBlurPotential;
			HDRpixels[ViewportWidth*y+x]=temp;
		}
	}
	}

	delete[] pixels;
}

void CCamera::RenderScene(CScene &scene,unsigned int *&pixels)
{
	CColor * Renderpixels = new CColor[RenderWidth * RenderHeight];

	RenderScene_ToHDR(scene,Renderpixels);
	CColor * fpixels = new CColor[ViewportWidth * ViewportHeight];
	omp_set_num_threads(4);
#pragma omp parallel shared(fpixels)
	{
	// Anti-Aliasing
#pragma omp for
	for(int p = 0; p < (ViewportHeight*ViewportWidth); ++p)
	{
		fpixels[p]=CColor(0.0,0.0,0.0);
	}	
#pragma omp for
	for(int y = 0; y < ViewportHeight; ++y) 
	{
		for(int x = 0; x < ViewportWidth; ++x) 
		{
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3)+y*3*RenderWidth])/(16.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3+1)+y*3*RenderWidth])/(8.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3+2)+y*3*RenderWidth])/(16.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[x*3+(y*3+1)*RenderWidth])/(8.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3+1)+(y*3+1)*RenderWidth])/(4.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3+2)+(y*3+1)*RenderWidth])/(8.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[x*3+(y*3+2)*RenderWidth])/(16.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3+1)+(y*3+2)*RenderWidth])/(8.0);
			fpixels[x+y*ViewportWidth]+=(Renderpixels[(x*3+2)+(y*3+2)*RenderWidth])/(16.0);
		}
	}
	}
	delete[] Renderpixels;

	CColor * HDRpixels = new CColor[ViewportWidth * ViewportHeight];
	Split_HDR(fpixels,HDRpixels);

	Fuzzify_HDR(HDRpixels);
	Fuzzify_HDR(HDRpixels);
	Fuzzify_HDR(HDRpixels);

	pixels = new unsigned int[ViewportWidth * ViewportHeight];

	omp_set_num_threads(4);

#pragma omp parallel
	{
	double Exposure =0.1395f;
	double Exposure2 =0.05395f;
#pragma omp for
	for(int y = 0; y < ViewportHeight; ++y) 
	{
		for(int x = 0; x < ViewportWidth; ++x) 
		{
			CByteColor Bcolor = CByteColor(1-exp(-1.0f*fpixels[x+y*ViewportWidth].r*Exposure-1.0f*HDRpixels[x+y*ViewportWidth].r*Exposure2),1-exp(-1.0f*fpixels[x+y*ViewportWidth].g*Exposure-1.0f*HDRpixels[x+y*ViewportWidth].g*Exposure2),1-exp(-1.0f*fpixels[x+y*ViewportWidth].b*Exposure-1.0f*HDRpixels[x+y*ViewportWidth].b*Exposure2));
//				CByteColor Bcolor = CByteColor(1-exp(-1.0f*fpixels[x+y*ViewportWidth].r*Exposure,1-exp(-1.0f*fpixels[x+y*ViewportWidth].g*Exposure),1-exp(-1.0f*fpixels[x+y*ViewportWidth].b*Exposure)));
//				CByteColor Bcolor = CByteColor(1-exp(-1.0f*HDRpixels[x+y*ViewportWidth].r*Exposure2),1-exp(-1.0f*HDRpixels[x+y*ViewportWidth].g*Exposure2),1-exp(-1.0f*HDRpixels[x+y*ViewportWidth].b*Exposure2));
			unsigned int &buffer = pixels[x+y*ViewportWidth];
			buffer = Bcolor.RGB();
		}
	}
	}
	delete[] fpixels;
	delete[] HDRpixels;

};

void CCamera::RenderScene_ToHDR(CScene &scene,CColor * Renderpixels)
{
	CVector direction = LookAt - Position;
	direction.Normalize();
	omp_set_num_threads(32);
	CVector right = direction.CrossProduct(CVector(0.0f, 1.0f, 0.0f));
	CVector up = right.CrossProduct(direction);

#pragma omp parallel shared(Renderpixels)
	{

#pragma omp for
		for(int p = 0; p < (RenderHeight*RenderWidth); ++p)
		{
			//std::cout << p*100.0/(ViewportHeight*ViewportWidth) << "%" << std::endl;
#if TILERENDERING
			int BlocPerLine = ViewportWidth/TILESIZE;
			int BlocNumber = p/(TILESIZE*TILESIZE);
			int BlocLine = BlocNumber/BlocPerLine;
			int BlocColumn = BlocNumber%BlocPerLine;
			int pixelInBloc = p%(TILESIZE*TILESIZE);

			int x=BlocColumn*TILESIZE+pixelInBloc%TILESIZE;
			int y=BlocLine*TILESIZE+(pixelInBloc-(pixelInBloc%TILESIZE))/TILESIZE;
#else
			int x=p%RenderWidth;
			int y=(p-x)/RenderWidth;
#endif
			CRay view;
			view.intensity = 1.0f;
			view.Origin = Position;
			view.BounceThreshold = MaxBounce;
			CColor ResultColor;
			double angle_x = (x * HFOV / RenderWidth) - (HFOV / 2);
			double angle_y = (y * VFOV / RenderHeight) - (VFOV / 2);
			if((angle_y>0)&&(angle_x>0))
				int w=0;
			view.Direction=direction*cos(angle_x)*cos(angle_y) + right*sin(angle_x)*cos(angle_y) + up*sin(angle_y);
			view.Direction.Normalize();
			scene.RenderRay(view,ResultColor);
			Renderpixels[x+y*RenderWidth]=ResultColor;
		}
	}
};


CRenderableObject * CCamera::Camera_GetObject(CScene * Scene, int x, int y)
{
	CVector direction = LookAt - Position;
	direction.Normalize();
	CVector right = direction.CrossProduct(CVector(0.0f, 1.0f, 0.0f));
	CVector up = right.CrossProduct(direction);
	CRay view;
	view.Origin = Position;
	view.BounceThreshold = MaxBounce;
	CColor ResultColor;
	double angle_x = (x * HFOV / ViewportWidth) - (HFOV / 2);
	double angle_y = ((ViewportHeight-y-1) * VFOV / ViewportHeight) - (VFOV / 2);
	view.Direction=direction*cos(angle_x)*cos(angle_y) + right*sin(angle_x)*cos(angle_y) + up*sin(angle_y);
	view.Direction.Normalize();
	return Scene->Scene_GetObject(view);
};

void CCamera::RenderScene_RAW(CScene &scene,unsigned int *&pixels)
{
	CColor * Renderpixels = new CColor[RenderWidth * RenderHeight];

	RenderScene_ToHDR(scene,Renderpixels);

	pixels = new unsigned int[ViewportWidth * ViewportHeight];

	omp_set_num_threads(4);

#pragma omp parallel
	{
		double Exposure =0.1395f;
		double Exposure2 =0.05395f;
#pragma omp for
		for(int y = 0; y < ViewportHeight; ++y) 
		{
			for(int x = 0; x < ViewportWidth; ++x) 
			{
								CByteColor Bcolor = CByteColor(1-exp(-1.0f*Renderpixels[x+y*ViewportWidth].r*Exposure),1-exp(-1.0f*Renderpixels[x+y*ViewportWidth].g*Exposure),1-exp(-1.0f*Renderpixels[x+y*ViewportWidth].b*Exposure));
				unsigned int &buffer = pixels[x+y*ViewportWidth];
				buffer = Bcolor.RGB();
			}
		}
	}
	delete[] Renderpixels;
};
